package best.driver.android.Map.location;

import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import best.driver.android.BestApp;
import best.driver.android.Map.Address;
import best.driver.android.Map.LatLng;
import best.driver.android.Model.BestDataBaseHelper;
import best.driver.android.Model.DriverPositionModel;
import best.driver.android.Utils.Logger;
import best.driver.android.Utils.TimeUtil;
import best.driver.android.manager.OrderManager;
import best.driver.android.manager.UserInfoManager;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import de.greenrobot.event.EventBus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class LocationManager {

    private final int REQUEST_LOCATION_TIME_OUT = 30 * 1000;

    private final int  retryTimeMax = 1;// 失败最多连续请求2次

    private LocationClient locationClient = null;

    private LocationClientOption option;

    private Logger logger = new Logger(LocationManager.class);

    private List<LocationListener> listeners = new ArrayList<LocationListener>();

    private int retryTimes = 0;

    private boolean locating = false;

    private Runnable timeOutRunnable;

    private Handler handler = new Handler(Looper.getMainLooper());

    public static LocationManager sInstance;


    public static LocationManager getInstance() {
        if(sInstance != null)
            return sInstance;
        sInstance = new LocationManager();
        return sInstance;
    }

    public boolean isLocating() {
        return locating;
    }

    public void init() {
        option = new LocationClientOption();
        option.setOpenGps(true); // 打开gps
        // option.setCoorType("gcj02"); // 设置坐标类型,默认值gcj02
        option.setCoorType("bd09ll"); // 设置坐标类型,默认值gcj02
        option.setScanSpan(5000); // 设置发起定位请求的间隔时间为5000ms
        option.setProdName("800best"); // 设置产品线名称
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        int span = 5000;
        option.setScanSpan(span);
        option.setIsNeedAddress(false);

        locationClient = new LocationClient(BestApp.getInstance());
        locationClient.setLocOption(option);
        locationClient.registerLocationListener(new BDLocationListener() {

            @Override
            public void onReceiveLocation(BDLocation location) {
                removeRequestLocationTimeOut();
                locating = false;
                if (location != null) {
                    int type = location.getLocType();
                    if (type == BDLocation.TypeGpsLocation || type == BDLocation.TypeNetWorkLocation) {
                        onGetLocation(location);
                    } else {
                        onFailed();
                        HashMap<String, String> params = new HashMap<String, String>();
                        params.put("type", String.valueOf(type));
                    }
                } else {
                    onFailed();
                    HashMap<String, String> params = new HashMap<String, String>();
                    params.put("type", "noType");
                }
            }
        });
    }

    /**
     * 停止定位服务
     */
    public void stopLocService() {
        if (locationClient != null) {
            locationClient.stop();
        }
        locating = false;
        removeRequestLocationTimeOut();
    }

    /**
     * 开始定位服务
     */
    public void startLocService() {
        if (locationClient != null) {
            locationClient.start();
        }
    }

    public void requestLoc() {
        requestLoc(false, 0);
    }

    public void requestLoc(int interval) {
        requestLoc(false, interval);
    }

    /**
     * 手动请求定位
     */
    public void requestLoc(boolean isRetry, int interval) {
        locationClient.getLocOption().setScanSpan(interval);
        if(!locationClient.isStarted()) {
            startLocService();
        }
        int result = locationClient.requestLocation();
        logger.d("locationClient requestLocation " + result + ", currentTime=" + TimeUtil.getcurrentTimes());
        if (result == 0) {
            addRequestLocationTimeOut();
            locating = false;
        } else if (result == 6) {
            BestApp.handler.sendEmptyMessage(11);
        }
        if (locationClient != null && locationClient.isStarted()) {
            if (!isRetry) {
                retryTimes = 1;
            }
            logger.d("locationClient requestLocation time" + System.currentTimeMillis() + "retryTimes" + retryTimes);
            if (locationClient.requestLocation() == 0) {
                addRequestLocationTimeOut();
                locating = false;
            }
        }
    }

    private void addRequestLocationTimeOut() {
        removeRequestLocationTimeOut();
        handler.postDelayed(getTimeOutRunnable(), REQUEST_LOCATION_TIME_OUT);
    }

    public void removeRequestLocationTimeOut() {
        if (timeOutRunnable != null) {
            handler.removeCallbacks(timeOutRunnable);
        }
    }

    private Runnable getTimeOutRunnable() {
        if (timeOutRunnable == null) {
            timeOutRunnable = new Runnable() {
                @Override
                public void run() {
                    locating = false;
                    onFailed();
                }
            };
        }
        return timeOutRunnable;
    }

    private void onGetLocation(BDLocation location) {
        if (location == null) {
            onFailed();
            return;
        }
        locating = true;

        Logger.d("relocation", System.currentTimeMillis()+" onGetLocation, Latitude=" + location.getLatitude() + ", Longitude=" + location
                .getLongitude() +
                ", LocType=" + location.getLocType() + ", Speed=" + location.getSpeed() + ", Radius=" + location.getRadius() + ", City=" + location.getCity() + ", NetworkLocationType=" +
                location.getNetworkLocationType() + ", Street=" + location.getStreet() + ", getTime=" + location
                .getTime() + ", CityCode=" + location.getCityCode() + ", Operators=" + location.getOperators());
        if(location.hasSpeed()) {
            if(location.getSpeed() > 140) {
                return;
            }
        }

        if(location.hasRadius()) {

        }

        Address currentAddress = new Address();
        currentAddress.setName(location.getAddrStr());
        LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
        EventBus.getDefault().post(new LatLng(location.getLatitude(), location.getLongitude()));
        currentAddress.setPoint(latLng);
        currentAddress.setAddressDetail(location.getStreet());
        String cityId = "";
        DriverPositionModel model = new DriverPositionModel();
        model.timeStamp = System.currentTimeMillis();
        model.lat = location.getLatitude();
        model.lng = location.getLongitude();
//        if(OrderManager.getInstance().getCurrentOrder() == null) {
//            model.lat = 30.28063;
//            model.lng = 120.128419;
//        }
        model.accelerate = location.getDerect();
        model.height = location.getAltitude();
        model.accuracy = location.getRadius();
        model.direction = location.getDirection();
        model.status = BestApp.mWorkStatus == null ? DriverPositionModel.WORK_STATUS_BUSY : BestApp.mWorkStatus;
        if(location.getLocType() == BDLocation.TypeNetWorkLocation) {
            model.type = "NET";
        } else if (location.getLocType() == BDLocation.TypeGpsLocation){
            model.type = "GPS";
        }
        if(UserInfoManager.getInstance().isCheckSucceed() && UserInfoManager.getInstance().isLogin()
                && OrderManager.getInstance().getCurrentOrder() != null && OrderManager.getInstance().canSavePosition(OrderManager.getInstance().getCurrentOrder().status)) {
            BestDataBaseHelper.getInstance().savePosition(model);
        }
        Logger.d("relocation", System.currentTimeMillis() + "save" + " " + model.toString());
        BestApp.getInstance().setLastKnowLocation(location.getLongitude(), location.getLatitude(), System.currentTimeMillis());
        BestApp.getInstance().uploadPosition();
        BestApp.getInstance().uploadPosition(model);
        OrderManager.getInstance().updateCurrentOrderModel(location.getLongitude(), location.getLatitude());

        if(!TextUtils.isEmpty(cityId)) {
            currentAddress.setCityId(cityId);
        }

    }

    private void onFailed() {
        locating = false;
        Logger.d("relocation", "retrytimes = " + retryTimes);
        if (retryTimes < retryTimeMax) {
            retryTimes++;
            BestApp.getInstance().handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    stopLocService();
                    requestLoc(true, 5000);
                }
            }, 1000);
        } else {
            stopLocService();
            BestApp.getInstance().handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    stopLocService();
                    requestLoc(true, 5000);
                }
            }, 1000);

        }
    }

    public boolean isStarted() {
        if(locationClient != null) {
            return locationClient.isStarted();
        }
        return false;
    }

}
